package cn.com.connected.service.impl;

import cn.com.connected.base.cache.CacheService;
import cn.com.connected.base.exception.BusinessException;
import cn.com.connected.base.exception.ErrorCode;
import cn.com.connected.base.utils.StringTools;
import cn.com.connected.common.config.AliyunSmsProperties;
import cn.com.connected.common.emnus.CacheKey;
import cn.com.connected.common.emnus.SmsType;
import cn.com.connected.dto.SmsDto;
import cn.com.connected.service.MemberService;
import cn.com.connected.service.SmsService;
import cn.com.connected.vo.MemberVo;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import static cn.com.connected.common.emnus.CacheKey.*;


/**
 * @author 邵明生
 * @version 3.0
 * @Description
 * @date 2020-09-08 19:52
 **/
@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Resource
    private MemberService memberService;

    @Resource
    private CacheService cacheService;

    @Resource
    private IAcsClient smsIAcsClient;

    @Resource
    private AliyunSmsProperties aliyunSmsProperties;


    @Value("${spring.profiles.active}")
    private String profile;

    @Override
    public void sendSmsMsg(SmsDto smsDto) {

        SmsType smsType = SmsType.getByValue(smsDto.getSmsType());
        String cacheErrorKey = StringTools.format(SMS_ERRORS, smsType.getValue(),smsDto.getMobile());
        String cacheKey = StringTools.format(CacheKey.SMS, smsType.getValue(),smsDto.getMobile());
        Integer cacheCode = cacheService.getObject(cacheKey);

        if (cacheCode!=null){
            log.warn("{}验证码已经发送，并且有效期内，暂时不予重新发送 验证码:{}",smsDto.getMobile(),cacheCode);
        }else{
            Integer code = 666666;
            if (profile.equals("prod") && false){
                code = randomCode(SMS_LENGTH);
                MemberVo member = memberService.memberInfoByMobile(smsDto.getMobile());

                //注册 但用户已存在
                if (smsType.equals(SmsType.REG) && member!=null){
                    throw new BusinessException(ErrorCode.DATA_USER_EXITS);
                }

                //非注册，但用户不存在
                if (!smsType.equals(SmsType.REG) && member==null){
                    throw new BusinessException(ErrorCode.DATA_USER_ERROR_EMPTY);
                }

                //非注册和登录外的情况，用户必须存在
                if ((!smsType.equals(SmsType.REG) && !smsType.equals(SmsType.LOGIN)) && member==null){
                    throw new BusinessException(ErrorCode.DATA_USER_ERROR_EMPTY);
                }

                sendSmsMsg(smsDto.getMobile(),code.toString(),smsType);
            }
            cacheService.putObject(cacheKey,code,SMS_EXPIRE_TIME);
            cacheService.putObject(cacheErrorKey,0,SMS_EXPIRE_TIME);
            log.warn("{}验证码发送成功 , 验证码:{}",smsDto.getMobile(),code);
        }
    }

    @Override
    public void sendSmsMsg(String mobile, String code,SmsType smsType) {

        String areaCode = "86";

        String templateCode = getTemplateCodeByType(smsType.getValue());

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", aliyunSmsProperties.getRegionId());
        request.putQueryParameter("PhoneNumbers", mobile);
        request.putQueryParameter("SignName", aliyunSmsProperties.getSignName());
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", "{'code':'"+code+"'}");
        try {
            CommonResponse response = smsIAcsClient.getCommonResponse(request);

            log.info(response.getData());
        } catch (ServerException e) {
            log.error("发送短信验证码失败，服务异常：{}",e);
            throw new BusinessException(ErrorCode.SERVICE_SMS_ERROR);
        } catch (ClientException e) {
            log.error("发送短信验证码失败，服务异常：{}",e);
            throw new BusinessException(ErrorCode.SERVICE_SMS_ERROR);
        }
    }

    /**
     * @Description 根据短信类型获取短信模板
     * @author 邵明生
     * @date 2020/9/10 10:39
     **/
    public String getTemplateCodeByType(Integer smsType){

        if (SmsType.REG.getValue().equals(smsType)){
            return aliyunSmsProperties.getReg();
        }else if(SmsType.LOGIN.getValue().equals(smsType)){
            return aliyunSmsProperties.getLogin();
        }else if(SmsType.FIND_PWD.getValue().equals(smsType)){
            return aliyunSmsProperties.getFindPwd();
        }else if(SmsType.RESET_PWD.getValue().equals(smsType)){
            return aliyunSmsProperties.getResetPwd();
        }else if(SmsType.RESET_PHONE.getValue().equals(smsType)){
            return aliyunSmsProperties.getUpdateMobile();
        }else{
            throw new BusinessException(ErrorCode.SERIOUS_REQUEST);
        }
    }


    @Override
    public void volatileSmsCode(Integer smsCode, SmsType smsType, String mobile){
        String cacheErrorKey = StringTools.format(SMS_ERRORS, smsType.getValue(),mobile);
        Integer cacheErrorCount = cacheService.getObject(cacheErrorKey);

        String cacheKey = StringTools.format(CacheKey.SMS, smsType.getValue(),mobile);
        Integer cacheCode = cacheService.getObject(cacheKey);

        if (cacheCode==null){
            throw new BusinessException(ErrorCode.SMS_EMPTY);
        }

        if (smsCode.intValue() == cacheCode.intValue()){
            cacheService.remove(cacheErrorKey,cacheKey);
        }else if (cacheErrorCount>SMS_MAX_ERROR_COUNT){
            cacheService.remove(cacheErrorKey,cacheKey);
            throw new BusinessException(ErrorCode.SMS_EMPTY);
        }else{
            cacheService.putObject(cacheErrorKey,++cacheErrorCount,SMS_EXPIRE_TIME);
            throw new BusinessException(ErrorCode.SMS_ERROR);
        }
    }
}
